package com.yunhe.authority.service.office.impl;

import com.alibaba.fastjson.JSON;
import com.yunhe.authority.client.OptionClient;
import com.yunhe.authority.domain.authority.RealStation;
import com.yunhe.authority.domain.company.Company;
import com.yunhe.authority.domain.office.Office;
import com.yunhe.authority.excel.ExcelBase;
import com.yunhe.authority.excel.ExcelImport;
import com.yunhe.authority.model.housing.*;
import com.yunhe.authority.repository.company.CompanyRepository;
import com.yunhe.authority.repository.office.OfficeRepository;
import com.yunhe.authority.repository.office.impl.OfficeDao;
import com.yunhe.authority.service.authority.RealStationService;
import com.yunhe.authority.service.office.OfficeService;
import com.yunhe.authority.util.ExportTemplateVo;
import com.yunhe.authority.util.PoiUtils;
import com.yunhe.common.constant.OfficeConts;
import com.yunhe.common.exception.ArgumentErrorException;
import com.yunhe.common.exception.ModelNotFoundException;
import com.yunhe.common.exception.ObjectNotFoundException;
import com.yunhe.common.exception.UniqueConstraintsException;
import com.yunhe.common.filter.ServerContextHolder;
import com.yunhe.common.util.CollectionUtil;
import com.yunhe.common.util.DateTimeUtils;
import com.yunhe.common.util.RedisClient;
import com.yunhe.common.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 厂房service
 * @author zhengbo
 * @date 2020/11/4 16:26
 */
@Service
@Slf4j
public class OfficeServiceImpl implements OfficeService {

    @Autowired
    private OfficeRepository officeRepository;

    @Autowired
    private CompanyRepository companyRepository;

    @Autowired
    private RealStationService realStationService;

    @Autowired
    private OfficeDao officeDao;

    @Autowired
    private RedisClient redisClient;

    @Autowired
    private OptionClient optionClient;

    private static List<String> housingType = Arrays.asList("厂房+办公","厂房","办公","商业","公寓","其他");

    private static LinkedBlockingQueue<Office> officeQueue = new LinkedBlockingQueue<>();

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public Office createOffice(Long realStationId, Long companyId, Office office) throws ObjectNotFoundException, UniqueConstraintsException {

        office.setCreateTime(DateTimeUtils.format(new Date()));
        office.setUpdateTime(DateTimeUtils.format(new Date()));
        Office existOffice = officeDao.findByName(office.getOfficeTitle());
        if (existOffice != null){
            throw new UniqueConstraintsException("房源名称已存在！");
        }
        Office newOffice = officeRepository.save(office);

        if (companyId != null) {
            findCompanyByCompanyId(companyId);
            officeRepository.bindCompanyById(companyId, newOffice.getId());
        }
        if (realStationId != null) {
            realStationService.realStationBindOffice(realStationId, newOffice.getId());
        }
        redisClient.set("OfficeName:" + newOffice.getId(), JSON.toJSONString(newOffice));
        return newOffice;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public Office updateOffice(Office office) throws UniqueConstraintsException {
        Long realStationId = office.getRealStationId();
        Office existOffice = officeDao.findByName(office.getOfficeTitle());
        if (existOffice != null && existOffice.getId().longValue() != office.getId().longValue()){
            throw new UniqueConstraintsException("房源名称已存在！");
        }
        //设置原来的状态、入驻企业等信息
        Office searchById = officeDao.searchById(office.getId());
        office.setOfficeStatus(searchById.getOfficeStatus());
        office.setCompanyId(searchById.getCompanyId());
        office.setCompanyName(searchById.getCompanyName());
        //先与之前的解绑，在与新的绑定
        realStationService.unbindOfficeByOfficeId(office.getId());
        office.setUpdateTime(DateTimeUtils.format(DateTimeUtils.PATTERN.DATETIME.value(),new Date()));
        Office newOffice = officeRepository.save(office);
        if (realStationId != null) {
            realStationService.realStationBindOffice(realStationId, newOffice.getId());
        }
        String officeName = redisClient.get("OfficeName:" + office.getId());
        if(!StringUtil.isEmpty(officeName)){
            redisClient.set("OfficeName:" + office.getId(), JSON.toJSONString(office));
        }
        return newOffice;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public Office updateSpecifyAttributes(Long id,
                                          Long buildingNumber,
                                          String officeName,
                                          String officeTitle,
                                          Double officeArea) throws ObjectNotFoundException {
        Optional<Office> optionalOffice = officeRepository.findById(id);
        if (!optionalOffice.isPresent()) {
            throw new ObjectNotFoundException("未找到厂房");
        }
        Office office = optionalOffice.get();
        Optional.ofNullable(buildingNumber).ifPresent(office::setBuildingNumber);
        Optional.ofNullable(officeName).ifPresent(office::setOfficeName);
        Optional.ofNullable(officeTitle).ifPresent(office::setOfficeTitle);
        Optional.ofNullable(officeArea).ifPresent(office::setOfficeArea);
        office = officeRepository.save(office);
        return office;
    }

    @Override
    public Office findById(Long officeId) {
        Map<String, Object> map = officeDao.findById(officeId);
        Optional<Office> optionalOffice = officeRepository.findById(officeId);
        Office office = optionalOffice.orElse(null);
        if(!CollectionUtil.isEmpty(map)){
            office.setRealStationId((Long) map.get("realStationId"));
            office.setRegionPark((String) map.get("regionPark"));
        }
        return office;
    }

    @Override
    public Iterable<Office> findByCompanyId(Long companyId) throws ObjectNotFoundException {
        findCompanyByCompanyId(companyId);
        Iterable<Office> offices = officeRepository.findByCompanyId(companyId);
        return offices;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void deleteById(Long id) throws ArgumentErrorException {
        Office office = officeDao.searchById(id);
        String officeStatus = office.getOfficeStatus();
        if (OfficeConts.OFFICE_STATUS_CODE.Booking.value().equals(officeStatus)){
            throw new ArgumentErrorException("该房源已被预定，不可删除！");
        }
        if (OfficeConts.OFFICE_STATUS_CODE.Rented.value().equals(officeStatus)){
            throw new ArgumentErrorException("该房源已被租赁，不可删除！");
        }
        if (OfficeConts.OFFICE_STATUS_CODE.Sold.value().equals(officeStatus)){
            throw new ArgumentErrorException("该房源已售卖，不可删除！");
        }
        officeRepository.deleteById(id);
    }

    @Override
    public Office findByStationIdAndOfficeName(Long stationId, String officeName) {
        return officeRepository.findByStationIdAndOfficeName(stationId,officeName);
    }

    @Override
    public Office findByStationIdAndOfficeTitle(Long stationId, String officeTitle) {
        Map<Long, Office> officeMap = new HashMap<>();
        Iterable<RealStation> realStations = realStationService.findRealStationByStationId(stationId);
        realStations.forEach(realStation -> {
            Office office = officeRepository.findByStationIdAndOfficeTitle(realStation.getId(), officeTitle);
            if (office != null) {
                officeMap.put(stationId, office);
            }

        });
        return officeMap.get(stationId);
    }

    @Override
    public Office findByRealStationIdAndOfficeTitle(Long realStationId, String officeTitle) {
        return officeRepository.findByStationIdAndOfficeTitle(realStationId, officeTitle);
    }

    @Override
    public Office findOfficeByStationIdAndTitle(Long stationId, String officeTitle) {
        return officeRepository.findOfficeByStationIdAndTitle(stationId, officeTitle);
    }

    @Override
    public void bindStation(Long stationId, Long id) {
        officeRepository.bindStation(stationId,id);
    }

    @Override
    public void bindCompany(Long companyId, Long id) {
        officeRepository.bindCompanyById(companyId,id);
    }

    @Override
    public void unbindCompany(Long companyId) {
        officeRepository.unbindCompanyById(companyId);
    }

    @Override
    public Office createOfficeByStationId(Long stationId, Office office) {
        Office newOffice = officeRepository.save(office);

        if (stationId != null) {
            officeRepository.bindStation(stationId, newOffice.getId());
        }
        return office;
    }

    @Override
    public Iterable<Office> findOfficesByRealStationId(Long id) {
        return officeRepository.findOfficesByRealStationId(id);
    }

    @Override
    public Iterable<OfficeBrief> getOfficeByCondition(FilterCondition filterCondition) {
        Iterable<OfficeBrief> results = null;
        if(CollectionUtil.isEmpty(filterCondition.getParkList())){
            Iterable<RealStation> realStations = realStationService.findRealStationByStationId(filterCondition.getStationId());
            if(realStations != null){
                List<Long> realStationIds = new ArrayList<>();
                for (RealStation realStation : realStations) {
                    realStationIds.add(realStation.getId());
                }
                filterCondition.setParkList(realStationIds);
            }
        }
        results = officeDao.getOfficeByCondition(filterCondition);
        return results;
    }

    @Override
    public OfficeAreaStatistics officeAreaStatistics(OfficeStatisticsCondition officeStatisticsCondition) {
        /*Iterable<RealStation> realStations = realStationService.findRealStationByStationId(stationId);
        List<Long> realStationIds = new ArrayList<>();
        OfficeAreaStatistics officeAreaStatistics = new OfficeAreaStatistics();
        if(realStations != null){
            for (RealStation realStation : realStations) {
                realStationIds.add(realStation.getId());
            }
        }
        List<Office> offices = officeRepository.getOfficeByRealStationIds(realStationIds);*/

        OfficeAreaStatistics officeAreaStatistics = new OfficeAreaStatistics();
        List<Long> realStationIds = new ArrayList<>();
        if (CollectionUtils.isEmpty(officeStatisticsCondition.getParkList())){
            //如果选择框选择的园区为空,统计该账号所在虚拟园区下的所有真实园区的数据
            Iterable<RealStation> realStations = realStationService.findRealStationByStationId(officeStatisticsCondition.getStationId());
            if (realStations != null){
                for (RealStation realStation : realStations) {
                    realStationIds.add(realStation.getId());
                }
            }
        }else {
            //统计所选园区下的数据
            for (String stationIdStr : officeStatisticsCondition.getParkList()) {
                Long stationIdLong = Long.valueOf(stationIdStr);
                realStationIds.add(stationIdLong);
            }
        }

        List<Office> offices = officeRepository.getOfficeByRealStationIds(realStationIds);
        if(!CollectionUtil.isEmpty(offices)){
            Map<String, List<Office>> maps = offices.stream().collect(Collectors.groupingBy(Office::getOfficeStatus));
            double sum = 0;
            for (String key : maps.keySet()){
                List<Office> officeList = maps.get(key);
                double partitionSum = 0;
                for (Office office : officeList) {
                    partitionSum += office.getOfficeArea();
                }
                sum += partitionSum;
                //空置
                if (OfficeConts.OFFICE_STATUS_CODE.Vacant.value().equals(key)){
                    officeAreaStatistics.setVacantArea(partitionSum);
                }
                //预定
                if (OfficeConts.OFFICE_STATUS_CODE.Booking.value().equals(key)){
                    officeAreaStatistics.setScheduledArea(partitionSum);
                }
                //已租
                if (OfficeConts.OFFICE_STATUS_CODE.Rented.value().equals(key)){
                    officeAreaStatistics.setLeasedArea(partitionSum);
                }
                //已售
                if (OfficeConts.OFFICE_STATUS_CODE.Sold.value().equals(key)){
                    officeAreaStatistics.setSoldArea(partitionSum);
                }
            }
            officeAreaStatistics.setTotalArea(sum);
            /*
            officeAreaStatistics.setVacantArea(maps.get(OfficeConts.OFFICE_STATUS_CODE.Vacant.value()) == null ? 0:maps.get(OfficeConts.OFFICE_STATUS_CODE.Vacant.value())
                    .doubleValue());
            officeAreaStatistics.setScheduledArea(maps.get(OfficeConts.OFFICE_STATUS_CODE.Booking.value()) == null ? 0:maps.get(OfficeConts.OFFICE_STATUS_CODE.Booking.value())
                    .doubleValue());
            officeAreaStatistics.setLeasedArea(maps.get(OfficeConts.OFFICE_STATUS_CODE.Rented.value()) == null ? 0:maps.get(OfficeConts.OFFICE_STATUS_CODE.Rented.value())
                    .doubleValue());
            officeAreaStatistics.setSoldArea(maps.get(OfficeConts.OFFICE_STATUS_CODE.Sold.value()) == null ? 0:maps.get(OfficeConts.OFFICE_STATUS_CODE.Sold.value())
                    .doubleValue());
            officeAreaStatistics.setTotalArea(officeAreaStatistics.getLeasedArea() + officeAreaStatistics.getScheduledArea() +
                    officeAreaStatistics.getSoldArea() + officeAreaStatistics.getVacantArea());
            */

            return keep2Decimal(officeAreaStatistics);
        }
        return keep2Decimal(officeAreaStatistics);
    }

    private OfficeAreaStatistics keep2Decimal(OfficeAreaStatistics officeAreaStatistics) {
        BigDecimal bdTotal = new BigDecimal(officeAreaStatistics.getTotalArea()).setScale(2, BigDecimal.ROUND_HALF_UP);
        BigDecimal bdLease = new BigDecimal(officeAreaStatistics.getLeasedArea()).setScale(2, BigDecimal.ROUND_HALF_UP);
        BigDecimal bdScheduled = new BigDecimal(officeAreaStatistics.getScheduledArea()).setScale(2, BigDecimal.ROUND_HALF_UP);
        BigDecimal bdSold = new BigDecimal(officeAreaStatistics.getSoldArea()).setScale(2, BigDecimal.ROUND_HALF_UP);
        BigDecimal bdVacant = new BigDecimal(officeAreaStatistics.getVacantArea()).setScale(2, BigDecimal.ROUND_HALF_UP);

        return new OfficeAreaStatistics(bdTotal.doubleValue(), bdVacant.doubleValue(), bdScheduled.doubleValue(), bdLease.doubleValue(), bdSold.doubleValue());
    }


    @Override
    public List<OfficeVo> getOfficeByRealStationId(OfficeQueryCondition officeQueryCondition) {
        List<OfficeVo> officeVos = new ArrayList<>();
        if(CollectionUtil.isEmpty(officeQueryCondition.getRealStation())){
            String projectCode = ServerContextHolder.getContext().getProjectCode();
            if(!StringUtil.isEmpty(projectCode)){
                Iterable<RealStation> realStations = realStationService.findRealStationByStationId(Long.valueOf(projectCode));
                List<Long> realStationIds = new ArrayList<>();
                if(realStations != null){
                    for (RealStation realStation : realStations) {
                        realStationIds.add(realStation.getId());
                    }
                    officeQueryCondition.setRealStation(realStationIds);
                }
            }
        }
        OfficeVo officeVo = new OfficeVo();
        officeVo.setId(-1);
        officeVo.setCode("01");
        officeVo.setName("公区");
        officeVo.setType("item");
        officeVos.add(officeVo);
        OfficeVo officeVo1 = new OfficeVo();
        officeVo1.setId(-2);
        officeVo1.setCode("02");
        officeVo1.setName("非公区");
        officeVo1.setType("item");
        //查询厂房
        List<Office> offices = officeDao.findOfficesByRealStationIdAnOfiiceTitle(officeQueryCondition);
        if(!CollectionUtil.isEmpty(offices)){
            List<OfficeVo> officeVoList = new ArrayList<>();
            for (Office office : offices) {
                OfficeVo officeVo3 = new OfficeVo();
                officeVo3.setId(office.getId());
                officeVo3.setCode(String.valueOf(office.getId()));
                officeVo3.setName(office.getOfficeTitle());
                officeVo3.setType("office");
                officeVoList.add(officeVo3);
            }
            officeVo1.setChildren(officeVoList);
        }
        officeVos.add(officeVo1);
        return officeVos;
    }

    @Override
    public Office findByCompanyIdAndOfficeId(Long companyId, Long officeId) {

        Office office = officeRepository.findByCompanyIdAndOfficeId(companyId, officeId);
        return office;
    }

    @Override
    public Office isAlreadyBindCompany(Long officeId) {
        return officeRepository.findAlreadyBindCompanyOfficeById(officeId);
    }

    @Override
    public Iterable<Office> searchVacantOfficesByRealStationId(Long realStationId) {
        return officeRepository.searchVacantOfficesByRealStationId(realStationId);
    }

    @Override
    public void downOfficeUploadTemplate(Long exportPeopleId, HttpServletResponse response) throws IOException {
        List<String> names = new ArrayList<>();
//        Map<String,String> map = new HashMap<>();
        List<ExportTemplateVo> exportTemplateVos  = new ArrayList<>();
        //获取项目id
        String projectCode = ServerContextHolder.getContext().getProjectCode();
        //数据处理
        if(!StringUtil.isEmpty(projectCode)){
            Long stationId = Long.valueOf(projectCode);
            Iterable<RealStation> realStations = realStationService.findRealStationByStationId(stationId);
            if(realStations != null){
                for (RealStation realStation : realStations) {
                    ExportTemplateVo exportTemplateVo = new ExportTemplateVo();
                    exportTemplateVo.setId(realStation.getId());
                    exportTemplateVo.setTitle(StringUtil.isEmpty(realStation.getAbbreviationName())?realStation.getEnterpriseFullName():realStation.getAbbreviationName());
                    exportTemplateVos.add(exportTemplateVo);
                    //names.add(realStation.getAbbreviationName());
                }
            }
        }else {
            Iterable<RealStation> realStations =  realStationService.findAll();
            if(realStations != null){
                for (RealStation realStation : realStations) {
                    ExportTemplateVo exportTemplateVo = new ExportTemplateVo();
                    exportTemplateVo.setId(realStation.getId());
                    exportTemplateVo.setTitle(StringUtil.isEmpty(realStation.getAbbreviationName())?realStation.getEnterpriseFullName():realStation.getAbbreviationName());
                    exportTemplateVos.add(exportTemplateVo);
                    //names.add(realStation.getAbbreviationName());
                }
            }
        }
        String[] data = new String[names.size()];

        names.toArray(data);
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource[] resources = resolver.getResources("classpath:office/office-template.xls");
        Resource resource = resources[0];
        InputStream inputStream = resource.getInputStream();
        // 获取模板文件
        //File fi = resource.getFile();
        POIFSFileSystem fs = new POIFSFileSystem(inputStream);
        //读取excel模板
        HSSFWorkbook workbook = new HSSFWorkbook(fs);
        //读取模板内所有sheet内容
        int numberOfSheets = workbook.getNumberOfSheets();
        for (int i = 0; i < numberOfSheets; i++) {
            HSSFSheet excelSheet = workbook.getSheetAt(i);
            //PoiUtils.addValidationToSheet(workbook, excelSheet, data, 'C', 1, 10000,i);
            //PoiUtils.addAutoMatchValidationToSheet(workbook, excelSheet, exportTemplateVos, 'C', 'C', 1,10000,i,"RealStation");
            PoiUtils.addValidationToSheet(workbook, excelSheet, exportTemplateVos, 'C', 1,10000,i,"RealStation");
        }

        // 隐藏存储下拉列表数据的sheet；可以注释掉该行以便查看、理解存储格式
        PoiUtils.hideTempDataSheet(workbook, workbook.getSheetIndex("sheetRealStation"));
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        workbook.write(os);
        byte[] content = os.toByteArray();
        InputStream is = new ByteArrayInputStream(content);
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + URLEncoder.encode("房源信息批量导入模板.xlsx", "utf-8"));
        ServletOutputStream sout = response.getOutputStream();
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;

        try {
            bis = new BufferedInputStream(is);
            bos = new BufferedOutputStream(sout);
            byte[] buff = new byte[2048];
            int bytesRead;
            while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
                bos.write(buff, 0, bytesRead);
            }
        } catch (Exception e) {
            log.error("厂房信息批量导入模板初始化失败:", e);
        } finally {
            if (bis != null) {
                bis.close();
            }
            if (bos != null) {
                bos.close();
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void importOffice(MultipartFile file) throws IOException, ArgumentErrorException, InterruptedException {
        if (file.isEmpty()) {
            throw new IOException("导入文件" + file.getName() + "不存在");
        }
        String projectCode = ServerContextHolder.getContext().getProjectCode();
        if(StringUtil.isEmpty(projectCode)){
            throw new ArgumentErrorException("请选择对应的项目进行操作！");
        }
        InputStream in = null;
        try {
            in = file.getInputStream();
            importData(file,Long.valueOf(projectCode));
        }  finally {
            in.close();
        }
    }

    public void importData(MultipartFile file,Long stationId) throws IOException, ArgumentErrorException, InterruptedException {

        int startRow = 1;// 第一行开始是正文
        List<Map<String, String>> result = new ArrayList<Map<String, String>>();
        // 去读Excel
        HSSFSheet sheet=null;
        Workbook workbook = ExcelBase.getWorkBook(file.getInputStream(), file.getOriginalFilename());
        FormulaEvaluator formulaEvaluator = new HSSFFormulaEvaluator((HSSFWorkbook) workbook);
        if (workbook != null) {
            for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
                sheet= (HSSFSheet) workbook.getSheetAt(i);
                if(housingType.contains(sheet.getSheetName())){
                    // 获取最后行号
                    int lastRowNum = sheet.getPhysicalNumberOfRows();
                    if (lastRowNum > 0) { // 如果>0，表示有数据
                        System.out.println("总行号:" + lastRowNum);
                    }
                    HSSFRow row = null;
                    // 循环读取每行数据
                    for (int j = startRow; j <= lastRowNum; j++) {
                        row = sheet.getRow(j);
                        Map<String, String> map = new HashMap<String, String>();
                        boolean parkFlag = false;
                        if(row != null){
                            //获取每个单元格
                            for (int k = 0; k < 24; k++) {
                                if(row != null  && null != row.getCell(k) && !row.getCell(k).equals("")){
                                    String value = new ExcelImport().getCellValue(row.getCell(k));
                                    switch (k){
                                        case 0:
                                            if(StringUtil.isEmpty(value)){
                                                throw new ArgumentErrorException("房源类型不能为空！");
                                            }else {
                                                map.put("housingTypeTitle",value);
                                            }
                                            break;
                                    }
                                    if(k != 0  && k != 23){
                                        map.put("name"+k,value);
                                        if(!StringUtil.isEmpty(map.get("name1")) && !StringUtil.isEmpty(map.get("name2"))){
                                            RealStation realStation = null;
                                            realStation = realStationService.findRealStationByStationIdAndAbbreviationName(stationId, value);
                                            if(realStation ==null){
                                                realStation = realStationService.findRealStationByStationIdAndTitle(stationId, value);
                                            }
                                            if(realStation != null){
                                                Office existOffice = officeRepository.findOfficesByRealStationIdAnOfiiceTitle(map.get("name1"),realStation.getId());
                                                if(existOffice != null){
                                                    throw new ArgumentErrorException(value + "已存在！");
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            if (!CollectionUtil.isEmpty(map)) {
                                result.add(map);
                            }else {
                                break;
                            }
                        }
                    }
                }
            }
        }
        if (result.size() == 0) {
            throw new ArgumentErrorException("入参校验错误");
        }else {
            parseData(result,stationId);
        }

    }

    private void parseData(List<Map<String, String>> result,Long stationId) throws InterruptedException {
        long startTime = System.currentTimeMillis();
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        executorService.submit(() -> {
            batchDataProcessing();
        });
        for (Map<String, String> map : result) {
            Office office = new Office();
            office.setCreateTime(DateTimeUtils.format(DateTimeUtils.PATTERN.DATETIME.value(), new Date()));
            office.setUpdateTime(DateTimeUtils.format(DateTimeUtils.PATTERN.DATETIME.value(), new Date()));
            String housingTypeTitle = map.get("housingTypeTitle");
            String housingType = "";
            switch(housingTypeTitle){
                case "厂房+办公":
                    housingType = OfficeConts.HOUSING_TYPE.FactoryWork.value();
                    break;
                case "厂房":
                    housingType = OfficeConts.HOUSING_TYPE.Factory.value();
                    break;
                case "办公":
                    housingType = OfficeConts.HOUSING_TYPE.Work.value();
                    break;
                case "商业":
                    housingType = OfficeConts.HOUSING_TYPE.Business.value();
                    break;
                case "公寓":
                    housingType = OfficeConts.HOUSING_TYPE.Apartment.value();
                    break;
                case "其他":
                    housingType = OfficeConts.HOUSING_TYPE.Others.value();
                    break;
            }
            if(!StringUtil.isEmpty(map.get("name1")) && !StringUtil.isEmpty(map.get("name2"))){
                String value = map.get("name2");
                RealStation realStation = null;
                realStation = realStationService.findRealStationByStationIdAndAbbreviationName(stationId, value);
                if(realStation ==null){
                    realStation = realStationService.findRealStationByStationIdAndTitle(stationId, value);
                }
                if(realStation != null){
                    office.setRealStationId(realStation.getId());
                    office.setRegion(realStation.getAreaAddress());
                    deal(map, housingType, 19, office);
                    officeQueue.add(office);
                }
            }
        }
        officeQueue.add(new Office());
        long endTime = System.currentTimeMillis();
        log.info("数据处理所需时间：{}",(endTime-startTime));
        log.info("数据处理结束");
        executorService.shutdown();
        executorService.awaitTermination(20, TimeUnit.SECONDS);
    }

    private void batchDataProcessing() {
        try {
            for (; ; ) {
                List<Office> dataLists = new ArrayList<>(50);
                for (int i = 0; i < 50; i++) {
                    Office take = officeQueue.take();
                    if (take == null || take.getRealStationId() ==null) {
                        if (!CollectionUtil.isEmpty(dataLists)) {
                            for (Office office : dataLists) {
//                                Office existOffice = officeDao.findByName(office.getOfficeTitle());
//                                if(existOffice != null){
//                                    throw new ArgumentErrorException(office.getOfficeTitle() + "已存在！");
//                                }
                                Office save = officeRepository.save(office);
                                realStationService.realStationBindOffice(save.getRealStationId(), save.getId());
                            }
                        }
                        return;
                    } else {
                        dataLists.add(take);
                    }
                }
                if (!CollectionUtil.isEmpty(dataLists)) {
                    for (Office office : dataLists) {
//                        Office existOffice = officeDao.findByName(office.getOfficeTitle());
//                        if(existOffice != null){
//                            throw new ArgumentErrorException(office.getOfficeTitle() + "已存在！");
//                        }
                        Office save = officeRepository.save(office);
                        realStationService.realStationBindOffice(save.getRealStationId(), save.getId());
                    }
                    dataLists.clear();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void deal(Map<String, String> map, String housingType, int columnCount, Office office) {
        OfficeConts.HOUSING_TYPE housing_type = OfficeConts.HOUSING_TYPE.byValue(housingType);
        office.setHousingType(housingType);
        office.setOfficeStatus(OfficeConts.OFFICE_STATUS_CODE.Vacant.value());
        office.setOfficeStatusTitle(OfficeConts.OFFICE_STATUS_CODE.Vacant.title());
        for (int i = 1; i < columnCount; i++) {
            String val = map.get("name" + i);
            if (!StringUtil.isEmpty(val)) {
                switch (i){
                    case 1:
                        //房源名称
                        office.setOfficeTitle(val);
                        break;
                    case 3:
                        //房源备案号
                        office.setOfficeRecordNo(val);
                        break;
                    case 4:
                        //房源面积
                        office.setFactoryArea(Double.parseDouble(val));
                        break;
                    case 5:
                        switch(housing_type){
                            case FactoryWork:
                                //(厂房+办公)办公及门卫面积
                                office.setOfficeGuardArea(Double.parseDouble(val));
                                break;
                            case Others:
                                //(其他)厂房层数
                                office.setOfficeFloorCountTitle(val);
                                office.setOfficeFloorCount(OfficeConts.OFFICE_FLOOR_COUNT_TYPE.getValue(val));
                                break;
                            default:
                                //(厂房、办公、商业、公寓)空地面积
                                office.setBlankArea(Double.parseDouble(val));
                                break;
                        }
                        break;
                    case 6:
                        switch(housing_type){
                            case FactoryWork:
                                //(厂房+办公)空地面积
                                office.setBlankArea(Double.parseDouble(val));
                                break;
                            case Others:
                                //(其他)厂房层高
                                office.setOfficeFloorHeight(Double.parseDouble(val));
                                break;
                            default:
                                //(厂房、办公、商业、公寓)厂房层数
                                office.setOfficeFloorCountTitle(val);
                                office.setOfficeFloorCount(OfficeConts.OFFICE_FLOOR_COUNT_TYPE.getValue(val));
                                break;
                        }
                        break;
                    case 7:
                        switch (housing_type){
                            case FactoryWork:
                                //(厂房+办公)厂房层数
                                office.setOfficeFloorCountTitle(val);
                                office.setOfficeFloorCount(OfficeConts.OFFICE_FLOOR_COUNT_TYPE.getValue(val));
                                break;
                            case Others:
                                //(其他)厂房楼层
                                office.setOfficeFloor(Integer.parseInt(val));
                                break;
                            default:
                                //(厂房、办公、商业、公寓)厂房层高
                                office.setOfficeFloorHeight(Double.parseDouble(val));
                                break;
                        }
                        break;
                    case 8:
                        switch(housing_type){
                            case FactoryWork:
                                //(厂房+办公)厂房层高
                                office.setOfficeFloorHeight(Double.parseDouble(val));
                                break;
                            case Others:
                                //(其他)市场参考价
                                office.setMarketReferencePrice(Double.parseDouble(val));
                                break;
                            default:
                                //(厂房、办公、商业、公寓)楼层
                                office.setOfficeFloor(Integer.parseInt(val));
                                break;
                        }
                        break;
                    case 9:
                        switch(housing_type){
                            case FactoryWork:
                                //(厂房+办公)楼层
                                office.setOfficeFloor(Integer.parseInt(val));
                                break;
                            case Others:
                                //(其他)空地参考价
                                office.setBlankReferencePrice(Double.parseDouble(val));
                                break;
                            default:
                                //(厂房、办公、商业、公寓)市场参考价
                                office.setMarketReferencePrice(Double.parseDouble(val));
                                break;
                        }
                        break;
                    case 10:
                        switch(housing_type){
                            case FactoryWork:
                                //(厂房+办公)办公层数
                                office.setOfficeFloorCount2Title(val);
                                office.setOfficeFloorCount2(OfficeConts.OFFICE_FLOOR_COUNT_TYPE.getValue(val));
                                break;
                            case Others:
                                //(其他)房源形态
                                office.setOfficeTypeTitle(val);
                                office.setOfficeType(OfficeConts.OFFICE_TYPE.getValue(val));
                                break;
                            default:
                                //(厂房、办公、商业、公寓)空地参考价
                                office.setBlankReferencePrice(Double.parseDouble(val));
                                break;
                        }
                        break;
                    case 11:
                        switch(housing_type){
                            case FactoryWork:
                                //(厂房+办公)办公层高
                                office.setOfficeFloorHeight2(Double.parseDouble(val));
                                break;
                            case Others:
                                //(其他)装修情况
                                office.setDecorationTitle(val);
                                office.setDecoration(OfficeConts.OFFICE_TYPE.getValue(val));
                                break;
                            default:
                                //(厂房、办公、商业、公寓)房源形态
                                office.setOfficeTypeTitle(val);
                                office.setOfficeType(OfficeConts.OFFICE_TYPE.getValue(val));
                                break;
                        }
                        break;
                    case 12:
                        switch(housing_type){
                            case FactoryWork:
                                //(厂房+办公)办公楼层
                                office.setOfficeFloor2(Integer.parseInt(val));
                                break;
                            case Others:
                                //(其他)配电容量
                                office.setDistributionCapacity(Double.parseDouble(val));
                                break;
                            default:
                                //(厂房、办公、商业、公寓)装修情况
                                office.setDecorationTitle(val);
                                office.setDecoration(OfficeConts.DECORATION.getValue(val));
                                break;
                        }
                        break;
                    case 13:
                        switch(housing_type){
                            case FactoryWork:
                                //(厂房+办公)市场参考价
                                office.setMarketReferencePrice(Double.parseDouble(val));
                                break;
                            case Others:
                                //(其他)房源介绍
                                office.setOfficeIntroduction(val);
                                break;
                            default:
                                //(厂房、办公、商业、公寓)配电容量
                                office.setDistributionCapacity(Double.parseDouble(val));
                                break;
                        }
                        break;
                    case 14:
                        switch(housing_type){
                            case FactoryWork:
                                //(厂房+办公)空地参考价
                                office.setBlankReferencePrice(Double.parseDouble(val));
                                break;
                            case Others:
                                //(其他)
                                break;
                            default:
                                //(厂房、办公、商业、公寓)房源介绍
                                office.setOfficeIntroduction(val);
                                break;
                        }
                        break;
                    case 15:
                        if (OfficeConts.HOUSING_TYPE.FactoryWork.value().equals(housingType)){
                            //房源形态
                            office.setOfficeTypeTitle(val);
                            office.setOfficeType(OfficeConts.OFFICE_TYPE.getValue(val));
                        }
                        break;
                    case 16:
                        if (OfficeConts.HOUSING_TYPE.FactoryWork.value().equals(housingType)){
                            //装修情况
                            office.setDecorationTitle(val);
                            office.setDecoration(OfficeConts.DECORATION.getValue(val));
                        }
                        break;
                    case 17:
                        if (OfficeConts.HOUSING_TYPE.FactoryWork.value().equals(housingType)){
                            //配电容量
                            office.setDistributionCapacity(Double.parseDouble(val));
                        }
                        break;
                    case 18:
                        if (OfficeConts.HOUSING_TYPE.FactoryWork.value().equals(housingType)){
                            //房源介绍
                            office.setOfficeIntroduction(val);
                        }
                        break;
                }

            }
        }
        office.setOfficeArea(new BigDecimal(office.getFactoryArea()).add(new BigDecimal(office.getOfficeGuardArea())).setScale(2,BigDecimal.ROUND_HALF_UP).doubleValue());
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public String setOfficeBooked(Long intentionId, Long chosenOffice, String companyName, String stauts) throws ArgumentErrorException, ModelNotFoundException {
        Office office = findById(chosenOffice);
        if (office ==null){
            throw new ModelNotFoundException("对应的厂房不存在");
        }
        if(OfficeConts.OFFICE_STATUS_CODE.Vacant.value().equals(stauts)){
            office.setCompanyName(null);
            office.setSettledCompanyId(null);
            office.setOfficeStatus(stauts);
        }else if("99".equals(stauts)){
            office.setStatusFlag("1");
        }else {
            office.setOfficeStatus(stauts);
            office.setCompanyName(companyName);
            office.setSettledCompanyId(intentionId);
            //判断当前厂房是否已经被预订或者已租 如果已经被预订或者出租，出售，给出响应的提示该厂房已被预订/出租/已售
            if(office.getSettledCompanyId() != null){
                if(intentionId.longValue() != office.getSettledCompanyId().longValue()){
                    String message =  "厂房名为："+office.getOfficeTitle()+"的厂房已被公司名称为"+office.getCompanyName()+ OfficeConts.OFFICE_STATUS_CODE.getTitle(office.getOfficeStatus());
                    return "error-"+message;
                }
                //throw new ArgumentErrorException();
            }
        }
        officeRepository.save(office);
        return "success";
    }

//    public static void main(String[] args) {
//        System.out.println(OfficeConts.OFFICE_STATUS_CODE);
//    }

    private void findCompanyByCompanyId(Long companyId) throws ObjectNotFoundException {
        Company company = companyRepository.findById(companyId);
        if (company == null) {
            throw new ObjectNotFoundException("未找到企业");
        }
    }
}
